#import "appController.h"
#import "MyPrefsWindowController.h"
//#define DEBUG


@implementation appController
//simple API that encodes reserved characters according to:
//RFC 3986
//http://tools.ietf.org/html/rfc3986
// found on http://mesh.typepad.com/blog/2007/10/url-encoding-wi.html
// slightly modified by tjcortez to not encode : or /
-(id) urlencode: (NSString *)url {
    NSArray *escapeChars = [NSArray arrayWithObjects:@";" , @"?"  ,
                                                        @"@" , @"&" , @"=" , @"+" ,
                                                        @"$" , @"," , @"[" , @"]",
                                                        @"#", @"!", @"'", @"(", 
                                                        @")", @"*", nil];

    NSArray *replaceChars = [NSArray arrayWithObjects:@"%3B" , @"%3F" ,
                                                         @"%40" , @"%26" ,
                                                        @"%3D" , @"%2B" , @"%24" ,
                                                        @"%2C" , @"%5B" , @"%5D", 
                                                        @"%23", @"%21", @"%27",
                                                        @"%28", @"%29", @"%2A", nil];

    int len = [escapeChars count];
    NSMutableString *temp = [url mutableCopy];
    int i;
    for(i = 0; i < len; i++)
    {
        [temp replaceOccurrencesOfString: [escapeChars objectAtIndex:i]
                                    withString:[replaceChars objectAtIndex:i]
                                    options:NSLiteralSearch
                                    range:NSMakeRange(0, [temp length])];
    }
    NSString *out = [NSString stringWithString: temp];
    return out;
}


+ (void)initialize{
	NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
	NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"192.168.1.100"
															forKey:@"xboxIP"];
	[userDefaults registerDefaults:appDefaults];
	NSDictionary *appDefaults2 = [NSDictionary dictionaryWithObject:@"192.168.1.101"
															 forKey:@"shareIP"];
	[userDefaults registerDefaults:appDefaults2];		
	NSDictionary *appDefaults3 = [NSDictionary dictionaryWithObject:@"1"
															forKey:@"pollingFreq"];
	[userDefaults registerDefaults:appDefaults3];
	[userDefaults synchronize];
	
	nothingIsPlayingOnXbox = 1;
	iTunesSyncOn = NO;
}
- (IBAction)openPreferencesWindow:(id)sender {
	[[MyPrefsWindowController sharedPrefsWindowController] showWindow:nil];
}
- (id)getInfoForTag: (NSString *)aTag  {
	if ([aTag isEqualToString: @"Thumb"]) {
		NSString *mainString = [self sendCommand:@"GetCurrentlyPlaying"];
		listItems = [mainString componentsSeparatedByString:@"<li>"];
	}
	NSEnumerator *enumerator = [listItems objectEnumerator];
	id anObject;
	while (anObject = [enumerator nextObject]) {
		//		NSLog(@"the thing: %@", anObject);
		if([aTag isEqualToString:@"File size"]) {
			return [[listItems lastObject] substringWithRange:NSMakeRange(10,[[listItems lastObject] length]-18)];
		 } 
		if([[anObject substringToIndex:4] isEqualToString:[aTag substringToIndex:4]]) {
			NSString *temp = [anObject substringFromIndex:[aTag length]+1];
#ifdef DEBUG
			NSLog(@"Returning %@",[temp substringToIndex:[temp length]-1]);
#endif
			return [temp substringToIndex:[temp length]-1];
		}
	}
	return @"";	
}

-(id) getiTunesPlayerState {
//	return @"";
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript       *scriptObject1 = [[NSAppleScript alloc] initWithSource: 
										  @"tell application \"iTunes\" \n \
										  set state to player state as string \n \
										  end tell \n"];
	returnDescriptor = [scriptObject1 executeAndReturnError: &errorDict];
	[scriptObject1 release];
	NSData	*rawData = [returnDescriptor data];
	NSString *playerState = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return playerState;
	
}

-(id) getiTunesTrackSize {
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript       *scriptObject1 = [[NSAppleScript alloc] initWithSource: 
										  @"tell application \"iTunes\" \n \
												if player state is not stopped then \n \
													set aSize to size of current track as string \n \
												end if \n\
										  end tell \n"];
	returnDescriptor = [scriptObject1 executeAndReturnError: &errorDict];
	[scriptObject1 release];
	NSData	*rawData = [returnDescriptor data];
	NSString *trackSize = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return trackSize;
}

-(id) muteiTunesAudio {
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript       *scriptObject1 = [[NSAppleScript alloc] initWithSource: 
										  @"tell application \"iTunes\" \n \
											set sound volume to 0 \n \
											end tell \n"];
	returnDescriptor = [scriptObject1 executeAndReturnError: &errorDict];
	[scriptObject1 release];
	NSData	*rawData = [returnDescriptor data];
	NSString *trackSize = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return trackSize;
}

-(id) unmuteiTunesAudio {
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript       *scriptObject1 = [[NSAppleScript alloc] initWithSource: 
										  @"tell application \"iTunes\" \n \
											set sound volume to 90 \n \
											end tell \n"];
	returnDescriptor = [scriptObject1 executeAndReturnError: &errorDict];
	[scriptObject1 release];
	NSData	*rawData = [returnDescriptor data];
	NSString *trackSize = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return trackSize;
}



-(id) getiTunesTrackLocation {
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource: 
											   @"tell application \"iTunes\" \n \
											   if player state is not stopped then \n \
											   set aLocation to location of current track \n \
											   tell application \"System Events\" \n \
											   set aLocation to URL of aLocation \n \
											   end tell \n \
											   else \n \
											   set aLocation to \"null\" \n \
											   end if \n \
											   end tell \n"];
	returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
	[scriptObject release];
	NSData	*rawData = [returnDescriptor data];
	NSString *trackLocation = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return [self urlencode: trackLocation];
}

-(id) getLocalIP {
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource: 
									@"try \n \
									set x to do shell script \"ipconfig getifaddr en1\" as text \n \
									on error \n \
									set x to \"\" \n \
									end try \n"];
	returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
	[scriptObject release];
	NSData	*rawData = [returnDescriptor data];
	NSString *localIP = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	[rawData release];
	return localIP;
}

-(void) synciTunes {
//			Fun debug crap
#ifdef DEBUG
			NSLog(@"Syncing iTunes");
			NSLog(@"iTunes playerstate = %@",[self getiTunesPlayerState]);
			NSLog(@"Xbox playerstate = %@",[self  getInfoForTag:@"PlayStatus"]);
			NSLog(@"iTunes tracksize = %@",[self getiTunesTrackSize]);
			NSLog(@"Xbox tracksize = %@",[self  getInfoForTag:@"File size"]);
#endif
			if ([@"paused" isEqualToString:[self getiTunesPlayerState]]) {
				if ([@"Paused" isEqualToString:[self  getInfoForTag:@"PlayStatus"]]) {
					// we are cool
				} else if ([@"Playing" isEqualToString:[self  getInfoForTag:@"PlayStatus"]]){
#ifdef DEBUG
					NSLog(@"Xbox is playing, we are pausing now.");
#endif
					[self sendCommand:@"pause"];
				}
			} else if ([@"playing" isEqualToString:[self getiTunesPlayerState]]) {
				if ([[self getiTunesTrackSize] isEqualToString:[self  getInfoForTag:@"File size"]]) {
#ifdef DEBUG
					NSLog(@"we are playing the right thing!");
#endif
					if ([@"Paused" isEqualToString:[self  getInfoForTag:@"PlayStatus"]]){
						[self sendCommand:@"pause"];
					}
				} else {
#ifdef DEBUG
					NSLog(@"Trying to make the xbox play the right junk");
#endif
					NSMutableString *mString = [[self getiTunesTrackLocation] mutableCopy];
					NSString *shareIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"shareIP"];
					NSString *shareUser = [[NSUserDefaults standardUserDefaults] stringForKey:@"shareUser"];
					NSString *sharePass = [[NSUserDefaults standardUserDefaults] stringForKey:@"sharePass"];
					NSString *firstPart = [@"smb://" stringByAppendingString:[shareUser stringByAppendingString:[@":" stringByAppendingString: sharePass]]];
					[mString replaceOccurrencesOfString:@"file://localhost/Users/" withString:[firstPart stringByAppendingString: [@"@" stringByAppendingString:[shareIP stringByAppendingString:@"/"]]] options:0 range:NSMakeRange(0, [mString length] - 1)];
					
					NSString *command = [@"PlayFile&parameter=" stringByAppendingString: mString];
//					NSLog(@"command to be sent: %@", command);
					[self sendCommand: command];
				}
			}
}

- (BOOL)xboxDetected {
	NSString *xboxIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"xboxIP"];
	NSDictionary        *errorDict;
	NSAppleEventDescriptor  *returnDescriptor;
	NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource: 
									[[@"try \n \
									set x to do shell script \"curl http://" stringByAppendingString:xboxIP] stringByAppendingString:@" --connect-timeout 1\" as text \n \
									on error \n \
									set x to \"no\" \n \
									end try \n"]];
	returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
	[scriptObject release];
	NSData	*rawData = [returnDescriptor data];
	NSString *results = [NSString stringWithCharacters:[rawData bytes] length: [rawData length] / sizeof(unichar)];
	if ([results isEqualToString:@"no"]) {
		[xbmcStatus setStringValue: [@"Cannot find xbox at " stringByAppendingString:xboxIP]];	
		[nowPlayingTitle setStringValue:@""];
		[nowPlayingArtist setStringValue:@""];
		[nowPlayingAlbum setStringValue:@""];
		[nowPlayingTime setStringValue:@""];
		[nowPlayingImage setImage:[NSImage imageNamed: @"null.png"]];

		return NO;
	} else {
	return YES;
	}
}


/******
 setFields
 ******/
- (void)setFields {
		// iTunes crap
//		NSLog(@"itunes syncing on? %@",iTunesSyncOn ? @"YES" : @"NO");
		if (iTunesSyncOn) {
		[self synciTunes];
		}
				
		// determine if something is playing or not.
		NSString *bigResult = [self sendCommand:@"GetCurrentlyPlaying"];
		listItems = [bigResult componentsSeparatedByString:@"<li>"];
		nothingIsPlayingOnXbox = [[listItems lastObject] isEqualToString:@"Filename:[Nothing Playing]</html>"];
		//	[playPercent startAnimation: self];
		if(nothingIsPlayingOnXbox) {
			[xbmcStatus setStringValue:@"Xbox Connected: Nothing Playing"];
			[nowPlayingTitle setStringValue:@""];
			[nowPlayingArtist setStringValue:@""];
			[nowPlayingAlbum setStringValue:@""];
			[nowPlayingTime setStringValue:@""];
			[nowPlayingImage setImage:[NSImage imageNamed: @"null.png"]];
			//		[playPercent setDoubleValue:0];
			//		[playPercent stopAnimation: self];
			
		}
		else {
			//					copy thumbnail to webserver
//			[self sendCommand:@"FileDelete&parameter=q:\\web\\temp.jpg"];
//			NSString *tStart = @"FileCopy&parameter=";
//			NSString *getThumb = [self getInfoForTag:@"Thumb"];
//			NSString *tEnd = @";q:\\web\\temp.jpg";
//			NSString *tFinal = [[tStart stringByAppendingString: getThumb]stringByAppendingString: tEnd];
//			NSLog(@"thumb: %@",tFinal);
//			
//			NSString *xboxIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"xboxIP"];
//			NSString *prefix = [[@"http://" stringByAppendingString: xboxIP] stringByAppendingString:@"/xbmcCmds/xbmcHttp?command="];
//			NSString *theCall1 = [prefix stringByAppendingString: @"FileDelete&parameter=q:\\web\\temp.jpg"];
//			NSString *theCall2 = [prefix stringByAppendingString: tFinal];
//			NSAppleScript *tempe = [[NSAppleScript alloc] initWithSource:[NSString stringWithFormat:@"set returnVal to do shell script \" /usr/bin/curl \'%@\'\" as string", theCall1]];
//			[tempe executeAndReturnError:nil];
//			NSString *copyCall = [NSString stringWithFormat:@"set returnVal to do shell script \" /usr/bin/curl \'%@\'\" as string", theCall2];
//			NSLog(@"copycall = %@", copyCall);
//			NSAppleScript *tempe2 = [[NSAppleScript alloc] initWithSource: copyCall];
//			NSString *whocares = [[tempe2 executeAndReturnError:nil] stringValue];
//			
//			//					NSString *whocares = [self sendCommand: tFinal];
//			NSLog(@"response: -%@-",whocares);
//			
//			
//			//set Image
//			xboxIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"xboxIP"];
//			prefix = [[@"http://" stringByAppendingString: xboxIP] stringByAppendingString:@"/temp.jpg"];
//			NSURL *imageURL = [NSURL URLWithString: prefix];
//			NSData *imageData = [imageURL resourceDataUsingCache:NO];
//			NSImage *imageFromBundle = [[NSImage alloc] initWithData: imageData];
//			if (imageFromBundle) {
//				[nowPlayingImage setImage:imageFromBundle];
//				[imageFromBundle release];
//			}
//			else {
//				NSLog(@"imageView could not be loaded.");			
				if ([[self getInfoForTag:@"Type"] isEqualToString:@"Video"]) {
					[nowPlayingImage setImage:[NSImage imageNamed: @"defaultVideoBig.png"]];
				}
				else if ([[self getInfoForTag:@"Type"] isEqualToString:@"Audio"]) {
					[nowPlayingImage setImage:[NSImage imageNamed: @"defaultAlbumCover.png"]];
					}
				
//			}
			[xbmcStatus setStringValue: [self  getInfoForTag:@"PlayStatus"]];
			[nowPlayingTitle setStringValue:[self  getInfoForTag:@"Title"]];
			[nowPlayingArtist setStringValue: [self  getInfoForTag:@"Artist"]];
			[nowPlayingAlbum setStringValue: [self  getInfoForTag:@"Album"]];
			NSString *divider = @" / ";
			NSString *temp = [self getInfoForTag:@"Time"];
			NSString *temp2 = [temp stringByAppendingString:[divider stringByAppendingString: [self getInfoForTag:@"Duration"]]];
			
			[nowPlayingTime setStringValue: temp2];
			
			// set progress
			//[playPercent setDoubleValue:[[self  getInfoForTag:@"Percentage"] doubleValue]];
	}
}

- (id) sendCommand: (NSString *)aCommand {
	if([self xboxDetected]) {

	NSString *xboxIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"xboxIP"];
	NSString *prefix = [[@"http://" stringByAppendingString: xboxIP] stringByAppendingString:@"/xbmcCmds/xbmcHttp?command="];
	NSURL *myURL = [NSURL URLWithString: [prefix stringByAppendingString: aCommand]];
#ifdef DEBUG
	NSLog(@"Executing command: %@",[prefix stringByAppendingString: aCommand]);
#endif
	NSURLRequest * urlRequest = [NSURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5.0];
	NSData * page = [[NSData alloc] initWithData:[NSURLConnection 
												  sendSynchronousRequest:urlRequest returningResponse:nil error:nil]];
	
	
	NSString * result = [[NSString alloc] initWithBytes:[page bytes] length:[page length] encoding:NSUTF8StringEncoding];
	return result;
	} else {
		return @"";
	}

}

- (void)awakeFromNib {
	[NSThread detachNewThreadSelector:@selector(bgThread:) toTarget:self withObject:nil];
}
- (void)bgThread:(NSConnection *)connection {
	#ifdef DEBUG
	NSLog(@"Opening up bgThread");
	#endif
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	while (YES) {
	if([[NSUserDefaults standardUserDefaults] stringForKey:@"xboxIP"] == NULL) {
		#ifdef DEBUG
		NSLog(@"xboxIP is null so don't do nuthing");
		#endif
			[xbmcStatus setStringValue: @"Enter xbox information in Preferences"];	
	} else {
		if ([self xboxDetected]) {
			[self setFields];
		}
			NSString *tempy = [[NSUserDefaults standardUserDefaults] stringForKey:@"pollingFreq"];

		if ([tempy isEqualToString:@"1"]) {
			[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
		}
		else {
			[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
		}
		}
	}
	[pool release];
	[NSThread exit];
}
- (IBAction)backTrack:(id)sender {
	[self sendCommand:@"PlayPrev"];	
}

- (IBAction)iTunesSync:(id)sender {
	if (iTunesSyncOn == NO) {
		iTunesSyncOn = YES;
		[self muteiTunesAudio];
	} else {
	iTunesSyncOn = NO;
	[self unmuteiTunesAudio];
	}
}
- (IBAction)forwardTrack:(id)sender {
	[self sendCommand:@"PlayNext"];
}
- (IBAction)playpause:(id)sender {
	[self sendCommand:@"pause"];
}
- (IBAction)sendKeyA:(id)sender {
	[self sendCommand:@"SendKey&parameter=256"];	
}
- (IBAction)sendKeyB:(id)sender {
	[self sendCommand:@"SendKey&parameter=257"];	
}
- (IBAction)sendKeyX:(id)sender {
	[self sendCommand:@"SendKey&parameter=258"];	
}
- (IBAction)sendKeyY:(id)sender {
	[self sendCommand:@"SendKey&parameter=259"];	
}
- (IBAction)sendKeyUp:(id)sender {
   if ([[NSApp currentEvent] type] == NSKeyUp)
       return;
	[self sendCommand:@"SendKey&parameter=270"];	
}
- (IBAction)sendKeyDown:(id)sender {
   if ([[NSApp currentEvent] type] == NSKeyUp)
       return;
	[self sendCommand:@"SendKey&parameter=271"];	
}
- (IBAction)sendKeyLeft:(id)sender {
   if ([[NSApp currentEvent] type] == NSKeyUp)
       return;
	[self sendCommand:@"SendKey&parameter=272"];	
}
- (IBAction)sendKeyRight:(id)sender {
   if ([[NSApp currentEvent] type] == NSKeyUp)
       return;
	[self sendCommand:@"SendKey&parameter=273"];	
}
- (IBAction)sendKeyWhite:(id)sender {
	[self sendCommand:@"SendKey&parameter=261"];	
}
- (IBAction)sendKeyBlack:(id)sender {
	[self sendCommand:@"SendKey&parameter=260"];	
}
- (IBAction)sendBack:(id)sender {
	[self sendCommand:@"SendKey&parameter=275"];	
}
- (IBAction)sendStart:(id)sender {
	[self sendCommand:@"SendKey&parameter=274"];	
}
- (IBAction)shutdown:(id)sender {
	[self sendCommand:@"Shutdown"];	
}
- (IBAction)restart:(id)sender {
	[self sendCommand:@"Restart"];	
		[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:8.0]];

}
- (IBAction)restartXBMC:(id)sender {
	[self sendCommand:@"Reset"];
	[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:8.0]];
	
}
@end
